package lionel.MyJMRI.MyTrain;

import java.awt.Image;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import javax.imageio.ImageIO;
import javax.swing.ImageIcon;
import javax.swing.JDesktopPane;
import javax.swing.JLabel;

import net.iharder.dnd.FileDrop;

import jmri.jmrit.XmlFile;
import jmri.jmrit.roster.Roster;
import jmri.jmrit.roster.RosterEntry;
import jmri.DccLocoAddress;
import jmri.LocoAddress;

import lionel.MyBrowser.MyBrowsableElement;

public class MyLocomotive extends JDesktopPane implements MyBrowsableElement, Comparable<MyLocomotive>, FileDrop.Listener
{
	private static final long serialVersionUID = -6433251119286601527L;

	static org.apache.log4j.Category log = org.apache.log4j.Category.getInstance(MyLocomotive.class.getName());
	
	static final String PATH_BASE = XmlFile.prefsDir()+"Images/";
	static final String PATH_FILE = "/image";
	static final String PATH_EXT =".jpg";
	
	protected LocoAddress mLocoAddress = null;	
	protected String mID = null;
	protected Image image = null;

	protected RosterEntry mRoster = null;
	protected JLabel bgImg = null;

	protected MyLocomotive(String id) 
	{
		super();
		if (id == null)
		{
			log.error("MyLocomotive() with null String");
			return;
		}
		this.mID = id;
		loadImage();
		new FileDrop(this, this);
	}
	
	protected MyLocomotive(MyLocomotive myLoc) 
	{ 
		super();
		if (myLoc == null)
		{
			log.error("MyLocomotive() with null MyLocomotive");
			return;
		}		
		this.mLocoAddress = myLoc.getAddress();
		this.mID = myLoc.ID();
		this.image = myLoc.getImage();
		loadImage();
		new FileDrop(this, this);
	}
	
	public int compareTo(MyLocomotive otherLoc) {
		return ( mID.compareTo(otherLoc.ID()));
	}
	
	public MyLocomotive(RosterEntry roster) {
		super();
		if (roster == null)
		{
			log.error("MyLocomotive() with null RosterEntry");
			return;
		}
		mLocoAddress = roster.getDccLocoAddress();
		mID = roster.getModel() + " - " + roster.getRoadName() + " " + roster.getRoadNumber();
		mRoster  = roster;
		loadImage();
		new FileDrop(this, this);
	}
	
	public MyLocomotive(LocoAddress address) {
		super();
		if (address == null)
		{
			log.error("MyLocomotive() with null LocoAddress");
			return;
		}
		List<RosterEntry> rosters;
		rosters = (List<RosterEntry>) Roster.instance().matchingList(null, null, ""+((DccLocoAddress)address).getNumber(), null, null, null, null) ;
		if (rosters.size() == 0)
		{
			log.warn("No roster for "+address);
			return ;
		}			
		if (rosters.size() != 1)
		{
			log.warn("Several rosters for "+address+", using first one");
		}
		RosterEntry roster = rosters.get(0);
		mLocoAddress = roster.getDccLocoAddress();
		mID = roster.getModel() + " - " + roster.getRoadName() + " " + roster.getRoadNumber();
		loadImage();
		new FileDrop(this, this);
	}
	
	private Boolean mDisplayed = false;
	
	public boolean isDisplayed()
	{ synchronized (mDisplayed) { return mDisplayed; } }
	
	public void setDisplayed(boolean dis)
	{ synchronized (mDisplayed) { mDisplayed = dis; }	}

	public void refresh()
	{
		if (image == null) loadImage();		
		ImageIcon imageIcon = new ImageIcon(image);
		if (bgImg!=null) this.remove(bgImg);
		bgImg = new JLabel(imageIcon);
		bgImg.setBounds(0, 0, imageIcon.getIconWidth(), imageIcon.getIconHeight());
		setPreferredSize( bgImg.getPreferredSize() );
		add(bgImg, new Integer(Integer.MIN_VALUE));
	}
	
	public void filesDropped(File[] files) {
		if (files == null)
			return;
		if (files.length == 0)
			return;
		setImage(files[0]);		
	}
	
	public LocoAddress getAddress()
	{
		return mLocoAddress ;
	}

	protected void loadImage()
	{
		if ((image==null) || (image.getWidth(null) == -1))
		{
			String imagePath = PATH_BASE + mID.trim() + PATH_FILE;

			int i=0;
			File file = new File(imagePath +i + PATH_EXT);
			while ( file.exists() )
			{ i++ ; file = new File(imagePath + i + PATH_EXT); }
			if (i>0)
				i--;
			log.debug("Loading image "+imagePath + i + PATH_EXT);
			File f = new File( imagePath + i + PATH_EXT );
			image = loadImage( f.toURI() );		
			if ((image==null) || (image.getWidth(null) == -1)) 
			{	
				try {
					if (mLocoAddress == null)
						image = loadImage(getClass().getResource("NoLocImage.jpg").toURI());
					else if (mLocoAddress.toString() == "0")
						image = loadImage(getClass().getResource("DCImage.jpg").toURI());
					else if (mLocoAddress.toString() == "3")
						image = loadImage(getClass().getResource("DCCImage.jpg").toURI());
					else
						image = loadImage(getClass().getResource("NoLocImage.jpg").toURI());
				} catch (URISyntaxException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
		}
	}
	
	protected Image loadImage(URI path)
	{
	    Image ret = null;
	    try {
			ret = ImageIO.read(path.toURL());
		} catch (Exception e) {
			log.error("Error loading image "+e+" on "+path);
		}
	    return ret;
	}
	
	public Image getImage()
	{
		return image;
	}
	
	public void setImage(File file)  
	{
		if (mID == null)
		{ log.warn("No roster at the moment"); return; }
		
		String imagePath;
		synchronized(mID) {	// need synchro because it's ran by the dnd listener thread
			imagePath = PATH_BASE + mID.trim() + PATH_FILE ; 
		}
		int i=0;
		File copy = new File(imagePath +i + PATH_EXT);
		while ( copy.exists() ) 
		{ i++ ; copy = new File(imagePath +i + PATH_EXT); }
	
		if (i==0)
			copy.getParentFile().mkdirs();			
			
		if ( copy.getParentFile().compareTo( file.getParentFile() ) != 0 )
		{  // copy file
			try
			{ copyFile(file, copy); }
		    catch (Exception e) 
		    { log.warn("Exception while copying file: "+e.toString()); }
		}
		else // move file in list
		{
			File prev = file;
			file.renameTo(copy); // rename to that name that will be loaded
			try
			{ prev.createNewFile(); } //create an empty file to fill slot
		    catch (Exception e) 
		    { log.warn("Exception while creating empty file: "+e.toString()); }
		}
		
		log.debug("File copied to "+ imagePath +i + PATH_EXT);
		loadImage();
		refresh();
	}
	
	private static void copyFile(File in, File out) throws Exception {
		    FileInputStream fis  = new FileInputStream(in);
		    FileOutputStream fos = new FileOutputStream(out);
		    try {
		        byte[] buf = new byte[1024];
		        int i = 0;
		        while ((i = fis.read(buf)) != -1) {
		            fos.write(buf, 0, i);
		        }
		    } 
		    catch (Exception e) {
		        throw e;
		    }
		    finally {
		        if (fis != null) fis.close();
		        if (fos != null) fos.close();
		    }
		  }
	
	public String toString()
	{
		if (mID != null)
			return(mID);
		if (mLocoAddress!=null)
			return(mLocoAddress.toString());
		return("No locomotive available");
	}
	
	public String ID()
	{ return(mID); }
}
